#include "head.h"
#include "md5.h"
extern struct order_t order;

void windows(int netfd,char* username,char* passwd)
{  
    while(1)
    {
        int choose=-1;
        printf( "\t╔════════════════welcome!══════════════════╗\n");  
        printf( "\t║         please choose function!          ║\n");  
        printf( "\t║                                          ║\n");  
        printf( "\t║                                          ║\n");  
        printf( "\t║              0: SIGN IN                  ║\n");  
        printf( "\t║              1: LOGIN                    ║\n");  
        printf( "\t║                                          ║\n");  
        printf( "\t║                                          ║\n");  
        printf( "\t╚══════════════════════════════════════════╝\n");
        scanf("%d\n",&choose);
        if(choose==0)
        {
            printf("please enter your username:%s",username);
            printf("\n");
            printf("please enter your passwd:%s",passwd);
            printf("\n");
            int ret=sign_in(netfd,username,passwd);
            if(ret==0)
            {
               break;
            }
            system("cls");
        }
        else if(choose==1)
        {
            printf("please enter your username:%s",username);
            printf("\n");
            printf("please enter your passwd:%s",passwd);
            printf("\n");
            int ret=login_user(netfd,username,passwd);
            if(ret==0)
            {
                break;
            }
            system("cls");
        }
        else
        {
            printf("input error!\n");
            system("cls");
        }
    }
}


int sign_in(int netfd,const char* name,const char* passwd)
{
    bzero(&order,sizeof(order));
    train_t train;
    order.order=SIGN_IN;
    strcpy(order.dir,passwd);
    strcpy(order.name,name);
    send(netfd,&order,sizeof(order),0);

    recvn(netfd,&train,sizeof(train));
    if(train.length==-1)
    {
        printf("ERROR:SIGN_IN FAULT!\n");
        return -1;
    }
    else
    {
        printf("SIGN_IN SUCCESS!\n");
        return 0;
    }
}

int sign_out(int netfd)
{
    bzero(&order,sizeof(order));
    train_t train;
    order.order=SIGN_IN;
    send(netfd,&order,sizeof(order),0);

    recvn(netfd,&train,sizeof(train));
    if(train.length==-1)
    {
        printf("ERROR:SIGN_OUT FAULT!\n");
        exit(-1);
    }
    else
    {
        printf("SIGN_OUT SUCCESS!\n");
        return 0;
    }
}

int login_user(int netfd,const char* name,const char* passwd)
{
    bzero(&order,sizeof(order));
    train_t train;
    order.order=LOGIN;
    strcpy(order.dir,passwd);
    strcpy(order.name,name);
    send(netfd,&order,sizeof(order),0);

    recvn(netfd,&train,sizeof(train));
    if(train.length==-1)
    {
        printf("username or passwd error!\n");
        exit_client(netfd);
        return -1;
    }
    else
    {
        printf("LOGIN SUCCESS!\n");
        return 0;
    }
}

int cd_dir(int netfd,const char*dir)
{
    bzero(&order, sizeof(order));
    train_t train;
    order.order=CD;
    strcpy(order.dir,dir);
    send(netfd,&order,sizeof(order),0);
    
    recvn(netfd,&train,sizeof(train));
    if(train.length==-1)
    {
        printf("cd,fault!\n");
        printf("%s\n",train.data);
    }
	else if(train.length==0)
    {
        printf("%s\n",train.data);
    }

    return 0;
}

int ls_dir(int netfd)
{
    bzero(&order, sizeof(order));
    train_t train;
    order.order=LS;
    send(netfd,&order,sizeof(order),0);
    recvn(netfd,&train,sizeof(train));
    if(train.length==-1)
    {
	printf("ls:fault!\n");
        printf("%s\n",train.data);
    }
    else if(train.length==0)
    {
	printf("ls:");
        printf("%s\n",train.data);
    }
    return 0;
}

int puts_file(int netfd,const char* name,const char* dir)       //文件名是MD5
{
    char md5[MD5_STR_LEN+1];
    int ret = Compute_file_md5(name, md5);
    if (0 == ret)
    {
        printf("[file - %s] md5 value:\n",name);
        printf("%s\n", md5);
    }
    else
    {
        printf("%s MD5SUM FAULT!\n",name);
        return -1;
    }

    bzero(&order, sizeof(order));
    order.order=PUTS;
    strcpy(order.name,md5);
    strcpy(order.dir,dir);
    send(netfd,&order,sizeof(order),0);
    
    train_t train;
    //接收服务端文件路径报错
    recvn(netfd,&train,sizeof(train));
    if(train.length==-1)
    {
        printf("%s\n",train.data);
        return -1;
    }
    //接收服务端报错：是否存在文件
    recvn(netfd,&train,sizeof(train));
    if(train.length==-1)        
    {
        printf("PUTS SUCESS!\n");
        return 0;
    }
    else if(train.length==0)    //服务端文件不存在，可以接收
    {
        printf("PUTS BEGIN!\n");
    }
    
    memset(&train,0,sizeof(train_t));
    train.length=strlen(name);
    memcpy(train.data,name,train.length);
    send(netfd,&train,sizeof(int)+train.length,MSG_NOSIGNAL);   //发送文件名

    int fd=open(name,O_RDWR);
    struct stat statbuf;
    fstat(fd,&statbuf);
    train.length=sizeof(statbuf.st_size);
    memcpy(train.data,&statbuf.st_size,train.length);
    send(netfd,&train,sizeof(int)+train.length,MSG_NOSIGNAL);   //发送文件大小

    if(statbuf.st_size<100*1024*1024)
    {
        while(1){
            bzero(&train,sizeof(train));
            ssize_t sret=read(fd,train.data,sizeof(train.data));
            train.length=sret;
            send(netfd,&train,sizeof(train),MSG_NOSIGNAL);
            if(sret==0)
            {
                break;
            }
        }
    }
    else
    {
        char *p=(char*)mmap(NULL,statbuf.st_size,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
        ERROR_CHECK(p,MAP_FAILED,"mmap");
        off_t totalsize=0;
        while(totalsize<statbuf.st_size)
        {
            if(statbuf.st_size-totalsize>1000)
            {
                train.length=1000;
            }
            else
            {
                train.length=statbuf.st_size-totalsize;
            }
            send(netfd,&train.length,sizeof(train.length),MSG_NOSIGNAL);
            send(netfd,p+totalsize,train.length,MSG_NOSIGNAL);
            totalsize+=train.length;
        }
        train.length=0;
        send(netfd,&train.length,sizeof(train.length),MSG_NOSIGNAL);
        munmap(p,statbuf.st_size);
    }
    close(fd);
    
    recvn(netfd,&train,sizeof(train));
    if(train.length==0)
    {
        printf("PUTS SUCESS!\n");
        return 0;
    }
    else
    {
        printf("PUTS FAULT!\n");
        printf("%s\n",train.data);
        return -1;
    }
}   

int gets_file(int netfd,const char* name,const char* dir)       //文件名是filename
{
    bzero(&order, sizeof(order));
    order.order=GETS;
    strcpy(order.name,name);
    strcpy(order.dir,dir);
    send(netfd,&order,sizeof(order),0);

    train_t train;
    //接收服务端文件报错  服务端是否存在文件
    recvn(netfd,&train,sizeof(train));
    if(train.length==-1)
    {
        printf("%s\n",train.data);
        return -1;
    }

    int fd=open(name,O_RDWR|O_CREAT,0666);
    struct stat statbuf;
    fstat(fd,&statbuf);
    train.length=sizeof(statbuf.st_size);
    memcpy(train.data,&statbuf.st_size,train.length);
    send(netfd,&train,sizeof(int)+train.length,MSG_NOSIGNAL);   //发送本地已有的文件大小
    
    int length;
    off_t filesize=0;       //直接接收服务器文件大小
    recvn(netfd,&length,sizeof(length));
    recvn(netfd,&filesize,length);

    //接收文件内容
    off_t cursize=statbuf.st_size;
    off_t slice=filesize/10000;
    off_t lastsize=cursize;
    if(filesize<100*1024*1024)
    {
        while(1)
        {
            char buf[4096]={0};
            recvn(netfd,&length,sizeof(length));
            if(length!=1000)
            {
                printf("length=%d\n",length);
            }
            if(length==0)
            {
                break;
            }
            recvn(netfd,buf,length);
            write(fd,buf,length);
            cursize+=length;
            if(cursize-lastsize>slice)
            {
                printf("%5.2lf%%\r",100.0*cursize/filesize);
                fflush(stdout);
                lastsize=cursize;
            }
        }
        printf("100.00%%\n");
        printf("gets success!\n");
    }
    else
    {
        ftruncate(fd,filesize);
        char *p=(char*)mmap(NULL,filesize,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
        ERROR_CHECK(p,MAP_FAILED,"mmap");
        recvn(netfd,p,filesize);
        munmap(p,filesize);
        printf("100.00%%\n");
	printf("gets success!\n");
        return 0;
    }
    //
    //接收服务端MD5码
    int md5_length=0;       //MD5的长度
    char md5[MD5_STR_LEN+1]={0};
    char md5_check[MD5_STR_LEN+1]={0};
    recvn(netfd,&md5_length,sizeof(int));
    recvn(netfd,md5,md5_length);
    
    //MD5加密验证文件正确性
    int ret = Compute_file_md5(name, md5_check);
	if (0 == ret)
	{
		printf("[file - %s] md5 value:\n",name);
		printf("%s\n", md5_check);
	}
    //校验MD5码    
    if(strcmp(md5,md5_check)==0)
    {
        printf("VERIFY SUCCESS!\n");
        close(fd);
        return 0;
    }
    else
    {
        printf("VERIFY FAULT!  File transfer failure\n");
        close(fd);
        return -1;
    }
}

int remove_file(int netfd,const char* name,const char* dir)
{
    bzero(&order, sizeof(order));
    train_t train;
    order.order=REMOVE;
    strcpy(order.name,name);
    strcpy(order.dir,dir);
    send(netfd,&order,sizeof(order),0);

    recvn(netfd,&train,sizeof(train));
    if(train.length==-1)
    {
	    printf("remove fault!\n");
        printf("%s\n",train.data);
    }
    return 0;
}

int pwd(int netfd)
{
    bzero(&order, sizeof(order));
    train_t train;
    order.order=PWD;
    send(netfd,&order,sizeof(order),0);

    recvn(netfd,&train,sizeof(train));
    if(train.length==-1)
    {
	printf("pwd fault!\n");
        printf("%s\n",train.data);
    }
    else if(train.length==0)
    {
        printf("%s\n",train.data);
    }
    return 0;
}

int mkdir_dir(int netfd,const char* name,const char* dir)
{
    bzero(&order, sizeof(order));
    train_t train;
    order.order=MKDIR;
    strcpy(order.name,name);
    strcpy(order.dir,dir);
    send(netfd,&order,sizeof(order),0);

    recvn(netfd,&train,sizeof(train));
    if(train.length==-1)
    {
	printf("mkdir fault!\n");
        printf("%s\n",train.data);
    }
    return 0;
}

int rmdir_dir(int netfd,const char* name,const char* dir)
{
    bzero(&order, sizeof(order));
    train_t train;
    order.order=RMDIR;
    strcpy(order.name,name);
    strcpy(order.dir,dir);
    send(netfd,&order,sizeof(order),0);

    recvn(netfd,&train,sizeof(train));
    if(train.length==-1)
    {
	    printf("rmdir fault!\n");
        //printf("%s\n",train.data);
    }
    return 0;
}

int exit_client(int netfd)
{
    bzero(&order, sizeof(order));
    train_t train;
    order.order=EXIT;
    send(netfd,&order,sizeof(order),0);

    recvn(netfd,&train,sizeof(train));
    if(train.length==-1)
    {
        printf("%s\n",train.data);
    }
    else if(train.length==0)
    {
        printf("EXIT SUCCESS!\n");
        exit(0);
    }
    return 0;
}

int recvn(int sockfd, void *buf, int length){
    int total = 0;
    char *p = (char *)buf;
    while(total < length){
        ssize_t sret = recv(sockfd,p+total,length-total,0);
        total += sret;
    }
    return total;
}
